#include <string.h> /* memcpy() */

#include "rcs.hh"               // LinkedList
#include "nml_intf/interpl.hh"  // these decls
#include "nml_intf/zuc.hh"
#include "nml_intf/zucglb.h"
#include "linklist.hh"
#include "nmlmsg.hh" /* class NMLmsg */
#include "rcs_print.hh"
#include <vector>

/*variables temporarily set here*/
int waitFlag = 0;         /* synchronized flag, shared by interp module and task module*/
bool waitTimeout = false; /* result of waitinput, timeout or not*/

pthread_mutex_t cmd_chn_lock;  // 锁以及状态

pthread_mutex_t glb_resources_lock;

pthread_mutexattr_t cmd_chn_lock_attr;

pthread_cond_t thread_cond = PTHREAD_COND_INITIALIZER;

std::atomic_bool thread_pause_flag;  ///<暂停标识
std::atomic_bool thread_exit_flag;
std::atomic_bool multi_thread_flag;

int threadInterpNum = 0;

ThreadInterpInfo threadInterpList[MAX_SUB_THREAD];

std::set<std::map<pthread_t, std::string>> threadStatusList;

NML_INTERP_LIST interp_list; /* NML Union, for interpreter */

NML_INTERP_LIST::NML_INTERP_LIST()
{
    linked_list_ptr = new LinkedList;

    next_line_number = 0;
    line_number = 0;
}

NML_INTERP_LIST::~NML_INTERP_LIST()
{
    if (NULL != linked_list_ptr)
    {
        delete linked_list_ptr;
        linked_list_ptr = NULL;
    }
}

int NML_INTERP_LIST::append(NMLmsg& nml_msg) { return append(&nml_msg); }

// sets the line number used for subsequent appends
int NML_INTERP_LIST::set_line_number(int line)
{
    next_line_number = line;

    return 0;
}

int NML_INTERP_LIST::append(NMLmsg* nml_msg_ptr)
{
    /* check for invalid data */
    if (NULL == nml_msg_ptr)
    {
        rcs_print_error("NML_INTERP_LIST::append : attempt to append NULL msg\n");
        return -1;
    }

    if (0 == nml_msg_ptr->type)
    {
        rcs_print_error("NML_INTERP_LIST::append : attempt to append 0 type\n");
        return -1;
    }

    if (nml_msg_ptr->size > MAX_NML_COMMAND_SIZE - 64)
    {
        rcs_print_error("NML_INTERP_LIST::append : command size is too large.");
        return -1;
    }
    if (nml_msg_ptr->size < 4)
    {
        rcs_print_error("NML_INTERP_LIST::append : command size is invalid.");
        return -1;
    }
#ifdef DEBUG_INTERPL
    if (sizeof(temp_node) < MAX_NML_COMMAND_SIZE + 4 || sizeof(temp_node) > MAX_NML_COMMAND_SIZE + 16 ||
        ((void*)&temp_node.line_number) > ((void*)&temp_node.command.commandbuf))
    {
        rcs_print_error("NML_INTERP_LIST::append : assumptions about NML_INTERP_LIST_NODE have been violated.");
        return -1;
    }
#endif

    if (NULL == linked_list_ptr)
    {
        return -1;
    }
    // fill in the NML_INTERP_LIST_NODE
    temp_node.line_number = next_line_number;
    memcpy(temp_node.command.commandbuf, nml_msg_ptr, nml_msg_ptr->size);

    // stick it on the list
    linked_list_ptr->store_at_tail(
        &temp_node, nml_msg_ptr->size + sizeof(temp_node.line_number) + sizeof(temp_node.dummy) + 32 + (32 - nml_msg_ptr->size % 32), 1);

    if (zuc_debug & ZUC_DEBUG_INTERP_LIST)
    {
        rcs_print("NML_INTERP_LIST(%p)::append(nml_msg_ptr{size=%ld,type=%s}) : list_size=%d, line_number=%d\n",
                  this,
                  nml_msg_ptr->size,
                  nml_msg_ptr->msg_name(),
                  linked_list_ptr->list_size,
                  temp_node.line_number);
    }

    return 0;
}

NMLmsg* NML_INTERP_LIST::get()
{
    NMLmsg* ret;
    NML_INTERP_LIST_NODE* node_ptr;

    if (NULL == linked_list_ptr)
    {
        line_number = 0;
        return NULL;
    }

    node_ptr = (NML_INTERP_LIST_NODE*)linked_list_ptr->retrieve_head();

    if (NULL == node_ptr)
    {
        line_number = 0;
        return NULL;
    }
    // save line number of this one, for use by get_line_number
    line_number = node_ptr->line_number;

    // get it off the front
    ret = (NMLmsg*)((char*)node_ptr->command.commandbuf);

    if (zuc_debug & ZUC_DEBUG_INTERP_LIST)
    {
        rcs_print("NML_INTERP_LIST(%p)::get(): {size=%ld, type=%s}, list_size=%d\n", this, ret->size, ret->msg_name(), linked_list_ptr->list_size);
    }

    return ret;
}

void NML_INTERP_LIST::clear()
{
    if (NULL != linked_list_ptr)
    {
        if (zuc_debug & ZUC_DEBUG_INTERP_LIST)
        {
            rcs_print("NML_INTERP_LIST(%p)::clear(): discarding %d items\n", this, linked_list_ptr->list_size);
        }

        linked_list_ptr->delete_members();
    }
}

void NML_INTERP_LIST::print()
{
    NMLmsg* ret;
    NML_INTERP_LIST_NODE* node_ptr;
    int line_number;

    if (NULL == linked_list_ptr)
    {
        return;
    }
    node_ptr = (NML_INTERP_LIST_NODE*)linked_list_ptr->get_head();

    rcs_print("NML_INTERP_LIST::print(): list size=%d\n", linked_list_ptr->list_size);
    while (NULL != node_ptr)
    {
        line_number = node_ptr->line_number;
        ret = (NMLmsg*)((char*)node_ptr->command.commandbuf);
        rcs_print("--> type=%s,  line_number=%d\n", ret->msg_name(), line_number);
        node_ptr = (NML_INTERP_LIST_NODE*)linked_list_ptr->get_next();
    }
    rcs_print("\n");
}

int NML_INTERP_LIST::len()
{
    if (NULL == linked_list_ptr)
    {
        return 0;
    }

    return ((int)linked_list_ptr->list_size);
}

int NML_INTERP_LIST::get_line_number() { return line_number; }
